//Input: 1)TestCaseName, will have to Check the database for any existing TestCases with similar name and report an error if so
                //       2)Directory of source code
                //       3)Users that can check the code and add test cases
                //TODO:setup function
#include <string>
#include <vector>
#include <iostream>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <cstdio>
#include <stdio.h>
#include <fstream>

#include "setup.h"
#include "query.h"
#include "util.h"

using namespace std;

//I am sure the project name is unique, and the directory of the project is valid and can proceed accordingly
int SetupNewCoverageProj(std::string ProjName, std::vector<std::string>& ProjMembers, std::string ProjDirectoryPath,int ManagerID)
{

///generate a pseudo-random number to represent the projects
int RandomNumber=0;
bool IsAvailable=true;
string RandomNumberString;
do{
	srand(time(NULL));
	RandomNumber+=rand();
	///make sure generateed number is positive for consistency incase I use -1 for invalid
	if(RandomNumber<0)
		RandomNumber*=-1;

	///Query to make sure number is not reserved for other functions
	string CheckIfRandomNumberUsedQuery="select exists(select 1 from Projects where ProjectKey=";
	RandomNumberString=ConvertIntToString(RandomNumber);
	CheckIfRandomNumberUsedQuery+=RandomNumberString;
	CheckIfRandomNumberUsedQuery+=")";
	Query CheckIfRandomNumberUsed(CheckIfRandomNumberUsedQuery);
	CheckIfRandomNumberUsed.Execute();
	string IsAvailableString=CheckIfRandomNumberUsed.GetLastElementReturned();	
	if(IsAvailableString=="1")
		IsAvailable=true;
	else
		IsAvailable=false;
}
while(IsAvailable==true);

///Got a unique key for the project, now insert it
string AddProjectQuery="INSERT INTO Projects VALUES ('";
AddProjectQuery+=ProjName;
AddProjectQuery+="',";
AddProjectQuery+=RandomNumberString;
AddProjectQuery+=",'";
AddProjectQuery+=ProjDirectoryPath;
AddProjectQuery+="')";
Query AddProject(AddProjectQuery);
AddProject.Execute();


///Associate the manager with the project. Announcing that he started it
string ManagerIDString=ConvertIntToString(ManagerID);
string AddProjectManagerRelationQuery="INSERT INTO ManagerProjects VALUES(";
AddProjectManagerRelationQuery+=ManagerIDString;
AddProjectManagerRelationQuery+=",";
AddProjectManagerRelationQuery+=RandomNumberString;
AddProjectManagerRelationQuery+=")";
Query AddProjectManagerRelation(AddProjectManagerRelationQuery);
AddProjectManagerRelation.Execute();

///Associate the manager with the project so he can use it
string AddProjectToManagerQuery="INSERT INTO ProjectUsers VALUES(";
AddProjectToManagerQuery+=RandomNumberString;;
AddProjectToManagerQuery+=",";
AddProjectToManagerQuery+=ManagerIDString;
AddProjectToManagerQuery+=")";
Query AddProjectToManager(AddProjectToManagerQuery);
AddProjectToManager.Execute();

//Send the list of Users with the project ID to a function whose role is to check if the user already exists. If so insert his id and the project id into ProjectUsers table
//Else add his email and the project ID into the NewUsers table
//Return the new number of users that this project created
int NewUsersCount=InsertMembersProjectRelation(ProjMembers,RandomNumberString);
return NewUsersCount;
}


bool IsProjNameAvailable(std::string ProjName)
{
///Check that the name the user intends to use s not used by another project
string CheckIfProjectNameAvailableQuery="select exists(select 1 from Projects where ProjectName='";
CheckIfProjectNameAvailableQuery+=ProjName;
CheckIfProjectNameAvailableQuery+="')";
Query CheckIfProjectNameAvailable(CheckIfProjectNameAvailableQuery);
CheckIfProjectNameAvailable.Execute();

string IsAvailableString=CheckIfProjectNameAvailable.GetLastElementReturned();

if(IsAvailableString=="1")//not available
	return false;
else if(IsAvailableString=="0")//available
	return true;
else
	{
        ;//TODO: report log file error
	}
//Never reached, used to remove warning
return false;
}


bool IsProjPathValid(std::string ProjDirectoryPath)
{
//The following used for directory:
//struct stat sb;
//if(stat(proj_path.c_str(),&sb)==0&&S_ISDIR(sb.st_mode))
//	return true;

//return false;

ifstream IsPathAvailable(ProjDirectoryPath.c_str());///Path available
if(IsPathAvailable)
	return true;

return false;

}


int InsertMembersProjectRelation(std::vector<std::string>& ProjMembers,std::string ProjKey)
{
int NewUsersCount=0;
///Associate each of the users with the project
for(unsigned int temp=0;temp<ProjMembers.size();temp++)
{
	///Get the user ID from his email
	string IsUserAlreadyRegisteredQuery="SELECT ID FROM Users WHERE Email='";
	IsUserAlreadyRegisteredQuery+=ProjMembers.at(temp);
	IsUserAlreadyRegisteredQuery+="';";
	Query IsUserAlreadyRegistered(IsUserAlreadyRegisteredQuery);
	IsUserAlreadyRegistered.Execute();
	string RegisteredUserID=IsUserAlreadyRegistered.GetLastElementReturned();
	if(RegisteredUserID!="")///User available in the system => associate him with project
		{
		string AddProjectToUserQuery="INSERT INTO ProjectUsers VALUES(";
		AddProjectToUserQuery+=ProjKey;
		AddProjectToUserQuery+=",";
		AddProjectToUserQuery+=RegisteredUserID;
		AddProjectToUserQuery+=");";
		Query AddProjectToUser(AddProjectToUserQuery);
		AddProjectToUser.Execute();
		}
	else///use email not available => new user => associate him in an inactive way such that when he registers his profile he will be able to work on this project
		{
		string AddProjectToNewUserQuery="INSERT INTO NewUsers VALUE('";
		AddProjectToNewUserQuery+=ProjMembers.at(temp);
		AddProjectToNewUserQuery+="',";
		AddProjectToNewUserQuery+=ProjKey;
		AddProjectToNewUserQuery+=");";
		Query AddProjectToNewUser(AddProjectToNewUserQuery);
		AddProjectToNewUser.Execute();
		NewUsersCount++;	
		}
}

return NewUsersCount;
}
